package nodes

import (
	"gitee.com/theegg/go-brick/app/model"
	"gitee.com/theegg/go-brick/app/model/content/tags"
	"gitee.com/theegg/go-brick/app/model/system/system_images"
	"gitee.com/theegg/go-brick/app/model/user/users"
	"gitee.com/theegg/go-brick/app/service/app"
	"gitee.com/theegg/go-brick/app/service/help/chtml"
	"gitee.com/theegg/go-brick/app/service/help/cslice"
	"regexp"
	"strings"
)

// 查询参数
type NodeQueryParams struct {
	PageSize  string `form:"page_size"  binding:"gte=0,lte=100" label:"每页数量"`
	PageIndex string `form:"page_index"  binding:"gte=0,lte=99999" label:"当前页数"`
	UserName  string `form:"username"  binding:"" label:"用户名"`
	Title     string `form:"title"  binding:"" label:"标题"`
}

// 添加参数
type NodeAddParams struct {
	Title        string `form:"title"  binding:"required,customPlainText=6 64" label:"标题"`
	Tags         string `form:"tags" binding:"omitempty,customMin=6,customMax=80" label:"标题"`
	Content      string `form:"content" binding:"required,customMin=3" label:"内容"`
	CategoryId   int    `form:"category_id" binding:"required" label:"分类"`
	UserId       int64  `form:"user_id" binding:"required" label:"作者"`
	CommentState int    `form:"comment_state" binding:"oneof=0 1" label:"禁止评论"`
	Summary      string `form:"summary" binding:"required,customPlainText=6 256" label:"摘要"`
	ImageCover   string `form:"image_cover" binding:"omitempty,customMin=6,customMax=64" label:"封面图"`
}

// tags最多4个
var NodeTagsItemMaxLength = 4

const (
	STATUS_POSTED    = 1  // 待审核
	STATUS_PUBLISHED = 2  // 已发布
	STATUS_DELETE    = -1 // 删除状态
)

// 新闻分类
var NodeCategory = []map[string]string{
	{
		"id":       "1",
		"title_en": "推荐",
		"title_cn": "推荐",
	},
	{
		"id":       "2",
		"title_en": "Hot News",
		"title_cn": "热点",
	},
	{
		"id":       "3",
		"title_en": "Work",
		"title_cn": "工作",
	},
	{
		"id":       "4",
		"title_en": "Local News",
		"title_cn": "本地",
	},
	{
		"id":       "5",
		"title_en": "Tourist",
		"title_cn": "旅游",
	},
}

// 分页获取所有数据
// @param params map 参数
// @return interface{}, error
func GetDataList(params map[string]interface{}) (map[string]interface{}, error) {
	returnData := make(map[string]interface{}, 0)

	queryParams, errBuild := model.BuildAdminQueryParam(params)
	if errBuild != nil {
		return nil, app.NewError(errBuild)
	}

	query := app.Db().Desc("id").Limit(queryParams.Limit, queryParams.Offset)

	// query lang
	if _, ok := queryParams.Params["lang"]; ok && queryParams.Params["lang"].(int) > 0 {
		query.Where("lang = ?", queryParams.Params["lang"])
	}

	// query category_id
	if _, ok := queryParams.Params["category_id"]; ok && queryParams.Params["category_id"].(int) > 0 {
		query.Where("category_id = ?", queryParams.Params["category_id"])
	}

	// query username
	if _, ok := queryParams.Params["username"]; ok && queryParams.Params["username"] != "" {
		query.Where("author_name = ?", queryParams.Params["username"])
	}

	// query title
	if _, ok := queryParams.Params["title"]; ok && queryParams.Params["title"] != "" {
		query.Where("title like ?", "%"+queryParams.Params["title"].(string)+"%")
	}

	data := make([]Nodes, 0)
	// 求总条数
	total, err := query.FindAndCount(&data)
	if err != nil {
		return nil, app.NewError(err)
	}

	for i, v := range data {
		categoryTitle := GetCategoryTitle(v.CategoryId)
		data[i].CategoryTitle = categoryTitle
		data[i].ImageCoverUrl = app.GetImageStaticUrl(data[i].ImageCover)
	}

	returnData["data"] = data
	returnData["total"] = total

	return returnData, nil
}

// @title AddOrUpdate
// @description 更新或者添加
func (n *Nodes) AddOrUpdate(params NodeAddParams) (*Nodes, error) {
	// 图片列表
	nodeOldImageList := make([]string, 0)

	imageChangeList := map[string][]string{
		"add": make([]string, 0),
		"del": make([]string, 0),
	}

	// 变更后的
	if n.ImageCover != "" {
		nodeOldImageList = append(nodeOldImageList, n.ImageCover)
	}

	if n.Content != "" {
		imageList := GetImageListFromContent(n.Content)
		nodeOldImageList = append(nodeOldImageList, imageList...)
	}

	// 分类
	if !HasNodeCategory(params.CategoryId) {
		return nil, app.NewError("Sorry, category not exit!")
	}

	// 作者
	author, errUser := users.GetItemById(params.UserId)
	if errUser != nil {
		return nil, app.NewError("Sorry, author not exit!")
	}

	n.Title = chtml.HtmlPlainText(params.Title)
	n.Summary = chtml.HtmlPlainText(params.Summary)
	n.Content = chtml.HtmlContentClean(params.Content)
	n.CategoryId = params.CategoryId
	n.AuthorId = author.Id
	n.AuthorName = author.Username
	n.CommentState = params.CommentState
	n.ImageCover = params.ImageCover
	n.State = 1

	// 3. 开启事务 插入数据
	session := app.Db().NewSession()
	defer session.Close()
	if errSession := session.Begin(); errSession != nil {
		return nil, app.NewError(errSession)
	}

	if n != nil && n.Id > 0 {
		affected, errUpdate := session.ID(n.Id).Update(n)

		if errUpdate != nil {
			session.Rollback()
			return nil, app.NewError(errUpdate)
		}

		if affected != 1 {
			session.Rollback()
			return nil, app.NewError("更新错误")
		}

	} else {
		n.State = STATUS_POSTED
		affected, errInsert := session.Insert(n)
		if errInsert != nil {
			session.Rollback()
			return nil, app.NewError(errInsert)
		}

		if affected != 1 {
			session.Rollback()
			return nil, app.NewError("新增菜单错误(0x001)")
		}
	}

	// 获取标签
	tagArr, errTag := GetTags(params.Tags)
	if errTag != nil {
		session.Rollback()
		return nil, app.NewError(errTag)
	}

	// 添加心标签
	_, err := tags.AddTagsToNode(tagArr, n.Id, params.UserId)
	if err != nil {
		session.Rollback()
		return nil, app.NewError(err)
	}

	// 图片列表
	nodeImageList := make([]string, 0)
	// 变更后的
	if n.ImageCover != "" {
		nodeImageList = append(nodeImageList, n.ImageCover)
	}

	if n.Content != "" {
		imageList := GetImageListFromContent(n.Content)
		nodeImageList = append(nodeImageList, imageList...)
	}

	// 哪些图片删除
	imageChangeList["del"] = append(imageChangeList["del"], cslice.StringSliceMainDiff(nodeOldImageList, nodeImageList)...)
	imageChangeList["add"] = append(imageChangeList["add"], cslice.StringSliceMainDiff(nodeImageList, nodeOldImageList)...)

	// 图片处理
	errImage := system_images.ProcessItemImage(n.Id, imageChangeList)
	if errImage != nil {
		session.Rollback()
		return nil, app.NewError(errImage)
	}

	// 提交
	errCommit := session.Commit()
	if errCommit != nil {
		return nil, app.NewError(errCommit)
	}

	return n, nil
}

// @title Publish
// @description 发布
func (n *Nodes) Publish() error {

	if n.State != STATUS_POSTED {
		return app.NewError("对不起,当前状态错误")
	}

	n.State = STATUS_PUBLISHED

	affected, errUpdate := app.Db().ID(n.Id).Cols("state").Update(n)

	if errUpdate != nil {
		return app.NewError(errUpdate)
	}

	if affected != 1 {
		return app.NewError("更新错误")
	}

	return nil
}

// @title UnPublish
// @description 下架
func (n *Nodes) UnPublish() error {

	if n.State != STATUS_PUBLISHED {
		return app.NewError("对不起,当前状态错误")
	}

	n.State = STATUS_POSTED

	affected, errUpdate := app.Db().ID(n.Id).Cols("state").Update(n)

	if errUpdate != nil {
		return app.NewError(errUpdate)
	}

	if affected != 1 {
		return app.NewError("更新错误")
	}

	return nil
}

// @title DeleteItem
// @description 下架
func (n *Nodes) DeleteItem() error {

	if n.State == STATUS_DELETE {
		return app.NewError("对不起, 当前内容已经被删除!")
	}

	n.State = STATUS_DELETE

	affected, errUpdate := app.Db().ID(n.Id).Cols("state").Update(n)

	if errUpdate != nil {
		return app.NewError(errUpdate)
	}

	if affected != 1 {
		return app.NewError("更新错误")
	}

	// 更新统计

	return nil
}

func GetTags(strTags string) ([]string, error) {
	tagArr := strings.Split(strTags, ",")

	if len(tagArr) > NodeTagsItemMaxLength {
		return nil, app.NewError("对不起, 一次最多4个tag!")
	}

	for _, tag := range tagArr {
		if !tags.CheckTag(tag) {
			return nil, app.NewError("对不起, tag不符合规定格式!")
		}
	}

	return tagArr, nil
}

// 获取单个数据
// @param id int64 数据的id
// @return *Nodes, error
func GetItemById(id int64) (*Nodes, error) {
	node := new(Nodes)
	has, err := app.Db().ID(id).Get(node)

	if err != nil {
		return nil, err
	}

	if !has {
		return nil, app.NewError("对不起, 目标对象不存在")
	}

	return node, nil
}

// 获取图片从内容
func GetImageListFromContent(str string) []string {
	baseImageUrl := app.GetImageBaseUrl()
	reg := `<img[^>]+\bsrc="` + baseImageUrl + `/(node/content/[0-9a-z\-]{36}\.(jpeg|jpg|png|gif))"`

	imageList := make([]string, 0)
	if str == "" {
		return imageList
	}

	re := regexp.MustCompile(reg)
	results := re.FindAllStringSubmatch(str, -1)
	for _, result := range results {
		imageList = append(imageList, result[1])
	}

	return imageList
}

// 获取分类的标题
func GetCategoryTitle(categoryId int) string {
	for i, v := range NodeCategory {
		if i == categoryId {
			return v["title_cn"]
		}
	}
	return ""
}

// 是否存在分类
func HasNodeCategory(categoryId int) bool {
	res := false
	for i, _ := range NodeCategory {
		if i == categoryId {
			res = true
			break
		}
	}
	return res
}
